package com.smile.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.smile.commons.tree.TreeBuilder;
import com.smile.mapper.MenuMapper;
import com.smile.mapper.RoleMenuMapper;
import com.smile.mapper.UserMapper;
import com.smile.model.domain.SmilePlusMenu;
import com.smile.model.domain.SmilePlusRoleMenu;
import com.smile.model.domain.SmilePlusUser;
import com.smile.model.dto.request.GetMenusByModuleTypeRequest;
import com.smile.model.response.response.GetMenusByRoleIdResponseDTO;
import com.smile.model.response.response.ShowMenuListResponseDto;
import com.smile.service.MenuService;
import com.smile.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private UserMapper userMapper;


    @Override
    public List<ShowMenuListResponseDto> getMenuList() {
        
        List<SmilePlusMenu> smilePlusMenus = List.of();
        if (SecurityUtils.isSuperAdmin()) {
            // 查询菜单列表:超级管理员查所有
            smilePlusMenus = menuMapper.selectList(null);
        } else {
            // 非超级管理员，则获取自己用户所对应角色的所有权限
            // 根据用户ID查询该用户下的所有菜单权限
            menuMapper.selectMenuByRoleIds(Long.valueOf(StpUtil.getLoginId().toString()));
        }
        
        List<ShowMenuListResponseDto> showMenuListResponseDtos = BeanUtil.copyToList(smilePlusMenus, ShowMenuListResponseDto.class);

        //转换为树
        List<ShowMenuListResponseDto> menuTree = TreeBuilder.buildTree(
                showMenuListResponseDtos,
                ShowMenuListResponseDto::getId,
                ShowMenuListResponseDto::getParentId,
                // 添加单个子节点的实现
                (parent, child) -> {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(child); // 正确添加单个子节点
                },
                node -> node.getParentId() == null || node.getParentId() == 0L
        );

        return menuTree;
    }


    @Override
    public List<GetMenusByRoleIdResponseDTO> getMenusByRoleId(Long id) {
        QueryWrapper<SmilePlusRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", id);
        List<SmilePlusRoleMenu> smilePlusRoleMenus = roleMenuMapper.selectList(queryWrapper);

        List<GetMenusByRoleIdResponseDTO> collect = smilePlusRoleMenus.stream().map(smilePlusRoleMenu -> {
            GetMenusByRoleIdResponseDTO getMenusByRoleIdResponseDTO = new GetMenusByRoleIdResponseDTO();
            BeanUtil.copyProperties(smilePlusRoleMenu, getMenusByRoleIdResponseDTO);
            return getMenusByRoleIdResponseDTO;
        }).collect(Collectors.toList());


        return collect;

    }

    @Override
    public List<ShowMenuListResponseDto> getMenuListAll() {
        // 1、查询所有菜单列表
        List<SmilePlusMenu> smilePlusMenus = menuMapper.selectList(null);
        List<ShowMenuListResponseDto> showMenuListResponseDtos = BeanUtil.copyToList(smilePlusMenus, ShowMenuListResponseDto.class);

        // 2、找到所有根节点
        List<ShowMenuListResponseDto> roots = showMenuListResponseDtos.stream().filter(menu -> menu.getParentId() == 0)
                .map(item -> {
                    // 3、递归获取子节点
                    item.setChildren(getChildrens(item, showMenuListResponseDtos));
                    return item;
                }).sorted((s1, s2) -> {
                    return (s1.getSort() == null ? 0 : s1.getSort()) - (s2.getSort() == null ? 0 : s2.getSort());
                }).toList();
        return roots;
    }

    /**
     * 递归获取子节点
     *
     * @param parentItem 父节点
     * @param all 所有菜单列表
     * @return 子节点列表
     */
    private List<ShowMenuListResponseDto> getChildrens(ShowMenuListResponseDto parentItem, List<ShowMenuListResponseDto> all) {
        return all.stream().filter(menu -> {
            return menu.getParentId().equals(parentItem.getId());
        }).map(item -> {
            // 递归获取子节点
            item.setChildren(getChildrens(item, all));
            return item;
        }).sorted((s1, s2) -> {
            return (s1.getSort() == null ? 0 : s1.getSort()) - (s2.getSort() == null ? 0 : s2.getSort());
        }).toList();
    }

    @Override
    public List<ShowMenuListResponseDto> getMenusByModuleType(GetMenusByModuleTypeRequest request) {
        // 1. 根据用户ID查询用户信息获取role_id
        Long userId = Long.parseLong(StpUtil.getLoginId().toString());
        SmilePlusUser user = userMapper.selectById(userId);
        if (user == null || user.getRoleId() == null) {
            return new ArrayList<>();
        }

        // 2.根据role_id查询角色菜单权限
        QueryWrapper<SmilePlusRoleMenu> roleMenuQuery = new QueryWrapper<>();
        roleMenuQuery.eq("role_id", user.getRoleId());
        List<SmilePlusRoleMenu> roleMenus = roleMenuMapper.selectList(roleMenuQuery);

        if (roleMenus.isEmpty()) {
            return new ArrayList<>();
        }

        // 提取菜单ID列表
        List<Long> menuIds = roleMenus.stream()
                .map(SmilePlusRoleMenu::getMenuId)
                .collect(Collectors.toList());

        // 3.根据菜单权限和模块类型查询菜单列表
        QueryWrapper<SmilePlusMenu> menuQuery = new QueryWrapper<>();
        menuQuery.in("id", menuIds)
                .eq("module_type", request.getModuleType())
                .orderByAsc("sort");

        List<SmilePlusMenu> menuList = menuMapper.selectList(menuQuery);
        List<ShowMenuListResponseDto> showMenuListResponseDtos = BeanUtil.copyToList(menuList, ShowMenuListResponseDto.class);

        showMenuListResponseDtos.forEach(System.out::println);

        // 4.转换为树结构
        List<ShowMenuListResponseDto> menuTree = TreeBuilder.buildTree(
                showMenuListResponseDtos,
                ShowMenuListResponseDto::getId,
                ShowMenuListResponseDto::getParentId,
                (parent, child) -> {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(child);
                },
                node -> node.getMenuType() != null && node.getMenuType() == 2L
        );

        return menuTree;
    }

    @Override
    public List<ShowMenuListResponseDto> getMenusByModuleTypeAll() {
        // 1. 根据用户ID查询用户信息获取role_id
        Long userId = Long.parseLong(StpUtil.getLoginId().toString());
        SmilePlusUser user = userMapper.selectById(userId);
        if (user == null || user.getRoleId() == null) {
            return new ArrayList<>();
        }

        // 2.根据role_id查询角色菜单权限
        QueryWrapper<SmilePlusRoleMenu> roleMenuQuery = new QueryWrapper<>();
        roleMenuQuery.eq("role_id", user.getRoleId());
        List<SmilePlusRoleMenu> roleMenus = roleMenuMapper.selectList(roleMenuQuery);

        if (roleMenus.isEmpty()) {
            return new ArrayList<>();
        }

        // 提取菜单ID列表
        List<Long> menuIds = roleMenus.stream()
                .map(SmilePlusRoleMenu::getMenuId)
                .collect(Collectors.toList());

        // 3.根据菜单权限和模块类型查询菜单列表
        QueryWrapper<SmilePlusMenu> menuQuery = new QueryWrapper<>();
        menuQuery.in("id", menuIds)
                // 去掉模块类型：返回该用户下面的全部拥有的菜单
//                .eq("module_type", request.getModuleType())
                .orderByAsc("sort");

        List<SmilePlusMenu> menuList = menuMapper.selectList(menuQuery);
        List<ShowMenuListResponseDto> showMenuListResponseDtos = BeanUtil.copyToList(menuList, ShowMenuListResponseDto.class);

        showMenuListResponseDtos.forEach(System.out::println);

        // 4.转换为树结构
        List<ShowMenuListResponseDto> menuTree = TreeBuilder.buildTree(
                showMenuListResponseDtos,
                ShowMenuListResponseDto::getId,
                ShowMenuListResponseDto::getParentId,
                (parent, child) -> {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(child);
                },
                node -> node.getMenuType() != null && node.getMenuType() == 2L
        );

        return menuTree;
    }

    @Override
    public List<Integer> getModules() {
        // 1. 根据用户ID查询用户信息获取role_id
        Long userId = Long.parseLong(StpUtil.getLoginId().toString());
        return menuMapper.getModules(userId);
    }
}
